﻿Imports System.Windows.Input
Namespace Commanding
    Public Class DelegateCommand(Of T)
        Implements ICommand

        Private m_canExecute As Func(Of T, Boolean)
        Private m_executeAction As Action(Of T)
        Private m_canExecuteCache As Boolean

        Public Sub New(ByVal executeAction As Action(Of T), ByVal canExecute As Func(Of T, Boolean))
            If executeAction Is Nothing AndAlso canExecute Is Nothing Then
                Throw New ArgumentNullException("executeAction")
            End If
            Me.m_canExecute = canExecute
            Me.m_executeAction = executeAction
        End Sub

        Public Function CanExecute(parameter As Object) As Boolean Implements ICommand.CanExecute
            Dim temp As Boolean = m_canExecute(parameter)
            If m_canExecuteCache <> temp Then
                m_canExecuteCache = temp
                RaiseEvent CanExecuteChanged(Me, New EventArgs())
            End If
            Return m_canExecuteCache
        End Function

        Public Event CanExecuteChanged(sender As Object, e As EventArgs) Implements ICommand.CanExecuteChanged

        Public Sub Execute(parameter As Object) Implements ICommand.Execute
            If m_executeAction Is Nothing Then
                Return
            End If
            If parameter Is Nothing Then
                m_executeAction(Nothing)
            Else
                m_executeAction(CType(parameter, T))
            End If
        End Sub

        'kind of useless
        Public Sub RaiseCanExecuteChanged()
            RaiseEvent CanExecuteChanged(Me, EventArgs.Empty)
        End Sub
    End Class
End Namespace